/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.autoescola.core.dao.security.role.impl;

import com.autoescola.core.dao.DaoImpl;
import com.autoescola.core.dao.DefaultDao;
import com.autoescola.core.dao.config.PersistenceContextConfig;
import com.autoescola.core.dao.security.role.RoleDao;
import com.autoescola.core.entity.security.Role;
import com.autoescola.core.entity.security.User;
import com.autoescola.core.entity.security.UserRole;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;

/**
 *
 * @author leonardo luz fernandes
 * @version 0.1
 * @since 01/11/2010
 */

@DefaultDao
@DaoImpl
public class RoleDaoImpl implements RoleDao {

    private static final Logger logger = Logger.getLogger(RoleDaoImpl.class.getCanonicalName());

    @PersistenceContext(name=PersistenceContextConfig.PERSISTENCE_CONTEXT_DEFAULT_NAME)
    private EntityManager entityManager;


    @Inject
    public void initialize(){
        logger.log(Level.INFO, "Calling initialize method of class: {0}", RoleDaoImpl.class.getCanonicalName());
    }//end method


    /**
     * Create a role
     * @param role
     * @return
     */

    @Override
    public Role create(Role role) {     
        this.entityManager.persist( role );
        this.entityManager.flush();
        return role;
    }//end method

    /**
     * Update a role
     * @param role
     * @return
     */

    @Override
    public Role update(Role role) {
        this.entityManager.persist( role );
        this.entityManager.flush();
        return role;
    }//end method

    /**
     * Delete a role
     * @param role
     * @return
     */

    @Override
    public boolean delete(Role role) {

        if( role.getId() == null ){
            throw new IllegalArgumentException("Role id cannot be null");
        }//end if

        String statement = 
        " DELETE FROM " + Role.class.getName() + " r WHERE r.id = :pId " ;
        Query query = this.entityManager.createQuery( statement );
        query.setParameter( "pId" , role.getId() );
        int result = query.executeUpdate();

        //Delete from the database but the object still living in the memory
        //until gc collect it.
        //this.entityManager.remove( role );



        if( result == 1 ){
            this.entityManager.detach( role );
        }//end if
        
        return result == 1 ? true : false ;

    }//end method

    /**
     * List avaliable roles.
     * @return
     */

    @Override
    public List<Role> list() {

        String statement = " SELECT * FROM " + Role.class.getName() ;
        Query query = this.entityManager.createQuery(statement);
        List<Role> result = (List<Role>)query.getResultList();
        
        return result;
        
    }//end method


    /**
     * List avaliable roles using a limit max of results
     * @param maxResult
     * @return
     */
    public List<Role> list( int maxResult ){

        if( maxResult <= 0 ){
            throw new IllegalArgumentException("Max Result must be greather then or equals 1.");
        }//end if

        String statement = "SELECT * FROM " + Role.class.getName() ;
        TypedQuery<Role> query = this.entityManager.createQuery(statement,Role.class);
        query.setMaxResults( maxResult );
        List<Role> result = query.getResultList();
        return result;

    }//end method

    /**
     * List avaliable roles
     * @param page
     * @param size
     * @return
     */
    public List<Role> list( int page , int size ){

        if( page <= 0 || size <= 0 ){
            throw new IllegalArgumentException("Page or Size must be greather then or equals 1.");
        }//end if


        String statement = "SELECT * FROM " + Role.class.getName() ;
        TypedQuery<Role> query = this.entityManager.createQuery(statement,Role.class);
        query.setMaxResults( size );

        int count = count();
        int pages = count / size ;

        if( !( page >= 1 && page <= pages ) ){
            throw new java.lang.IllegalArgumentException("Invalid page index! Page index must be between 1 and " + pages );
        }//end if

        query.setFirstResult( ( page - 1 ) * size  );

        List<Role> result = query.getResultList();

        return result;

    }//end method

    /**
     * Number of roles
     * @return
     */

    public int count(){

        String statement = "SELECT COUNT(*) FROM " + Role.class.getName();
        Query query = this.entityManager.createNamedQuery(statement);
        Number result = (Number)query.getSingleResult();
        return result.intValue() ;

    }//end method

    /**
     * Number of pages given a number of elements
     * @param size
     * @return
     */
    public int pages( int size ){

        if( size <= 0 ){
            throw new IllegalArgumentException("Size must be greather then or equals 1.");
        }//end

        String statement = "SELECT COUNT(*) FROM " + Role.class.getName();
        Query query = this.entityManager.createNamedQuery(statement);
        Number result = (Number)query.getSingleResult();
        return result.intValue() / size ;
        
    }//end method

    /**
     * Create a relation of user and role
     * @param user
     * @param role
     * @return
     */
    @Override
    public boolean add(User user, Role role) {

        if( user.getId() != null && role.getId() != null ){

            UserRole userRole = new UserRole();
            userRole.setUser(user);
            userRole.setRole(role);
            this.entityManager.persist( userRole );
            return userRole.getId() != null ;

        }else{
            throw new IllegalArgumentException("User id and Role id cannot be null");
        }//end else

    }//end method

    /**
     * Remove a relation of user and role
     * @param user
     * @param role
     * @return
     */
    @Override
    public boolean remove(User user, Role role) {

        if( user.getId() != null && role.getId() != null ){

            String statement = "DELETE FROM " + UserRole.class.getName() +
            " u WHERE u.user.id = :pUserId AND u.role.id = :pRoleId " ;

            Query query = this.entityManager.createQuery(statement);


            query.setParameter("pUserId",user.getId());
            query.setParameter("pRoleId",role.getId());

            int result = query.executeUpdate();

            return result >= 1 ;

        }else{
            throw new IllegalArgumentException("User Id and Role Id cannot be null.");
        }//end else

    }//end method

    /**
     * List roles of a given user
     * @param user
     * @return
     */
    @Override
    public List<Role> listRoles(User user) {

        if( user.getId() == null ){
            throw new IllegalArgumentException("User id cannot be null");
        }//end if

        String statement = " SELECT ur.role FROM " + UserRole.class.getName() +
        " ur WHERE us.user.id = :pUserId " ;

        TypedQuery<Role> query = this.entityManager.createQuery(statement, Role.class );
        query.setParameter("pUserId", user.getId() );
        List<Role> roles = query.getResultList();

        return roles;

    }//end method

    /**
     * List users of a given role
     * @param role
     * @return
     */
    @Override
    public List<User> listUsers(Role role) {

        if( role.getId() == null ){
            throw new IllegalArgumentException("Role id cannot be null");
        }//end if

        String statement = " SELECT ur.user FROM " + UserRole.class.getName() +
        " ur WHERE us.role.id = :pRoleId " ;

        TypedQuery<User> query = this.entityManager.createQuery(statement, User.class);
        query.setParameter("pRoleId", role.getId() );
        List<User> users = query.getResultList();
        
        return users;

    }//end method
    
}//end klazz
